package com.landlords.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.landlords.constants.PokerConstatns;
import com.landlords.model.ComparatorPoker;
import com.landlords.model.Poker;

/**
 * 扑克牌的方法
 * 
 * @author samoin
 * @since 2011-5-31
 */
public class PokerService {

	/**
	 * 对扑克牌排序
	 * 
	 * @param pokerList
	 * @return 排序后的扑克牌数组
	 */
	public static List<Poker> sortPokerList(List<Poker> pokerList) {
		if (pokerList == null || pokerList.size() <= 1) {
			return pokerList;
		}
		Collections.sort(pokerList, new ComparatorPoker());
		return pokerList;
	}

	/**
	 * 洗牌
	 * 
	 * @param pokerList
	 * @return
	 */
	public static List<Poker> shuffle(List<Poker> pokerList) {
		List<Poker> tempList = new ArrayList<Poker>();
		while (pokerList.size() > 0) {
			int tempIndex1 = (int) (Math.random() * pokerList.size());
			tempList.add(pokerList.get(tempIndex1));
			pokerList.remove(tempIndex1);
		}
		return tempList;
	}

	/**
	 * 判断是否是一对
	 * 
	 * @param pokerList
	 * @return
	 */
	public static boolean isPair(List<Poker> pokerList) {
		if (pokerList == null || pokerList.size() != 2) {
			return false;
		}
		return pokerList.get(0).getNum() == pokerList.get(1).getNum();
	}

	/**
	 * 判断是否是炸弹(8888)
	 * 
	 * @param pokerList
	 * @return true为是，false为不是
	 */
	public static boolean isBomb(List<Poker> pokerList) {
		sortPokerList(pokerList);
		if (pokerList != null && pokerList.size() == 2 && isAllKings(pokerList)) {
			return true;
		}
		if (pokerList == null || pokerList.size() != 4) {
			return false;
		}
		boolean flag = true;
		int tempNum = 0;
		for (Poker poker : pokerList) {
			int pokerNum = poker.getNum();
			if (tempNum == 0) {
				tempNum = pokerNum;
				continue;
			}
			if (tempNum != pokerNum) {
				flag = false;
				break;
			}
		}
		return flag;
	}

	// 是否是大小王
	private static boolean isAllKings(List<Poker> pokerList) {
		boolean flag = false;
		if (pokerList.size() == 2) {
			int poker1 = pokerList.get(0).getNum();
			int poker2 = pokerList.get(1).getNum();
			if ((poker2 == PokerConstatns.POKER_NUM_OLD_KING && poker1 == PokerConstatns.POKER_NUM_YONG_KING)
					|| (poker2 == PokerConstatns.POKER_NUM_OLD_KING && poker1 == PokerConstatns.POKER_NUM_YONG_KING)) {
				flag = true;
			}
		}
		return flag;
	}

	/**
	 * 判断是否是顺子(34567)
	 * 
	 * @param pokerList
	 * @return true为是，false为不是
	 */
	public static boolean isShunzi(List<Poker> pokerList) {
		if (pokerList == null || pokerList.size() < 5 || pokerList.size() > 13) {
			return false;
		}
		boolean flag = true;
		sortPokerList(pokerList);
		int tempNum = 0;
		int pokerListLen = pokerList.size();
		if (isShun(pokerList)) {
			return true;
		}
		for (int i = 0; i < pokerListLen; i++) {
			Poker poker = pokerList.get(i);
			int pokerNum = poker.getNum();
			if (tempNum == 0) {
				tempNum = pokerNum;
				continue;
			}
			if (pokerNum == PokerConstatns.POKER_NUM_ONE
					&& i != pokerListLen - 1) {
				flag = false;
				break;
			}
			if (tempNum != pokerNum - 1) {
				if (pokerNum != PokerConstatns.POKER_NUM_ONE
						|| i != pokerListLen - 1)
					flag = false;
				break;
			}
			tempNum = pokerNum;
		}
		return flag;
	}

	private static boolean isShun(List<Poker> pokerList) {
		int pokerListLen = pokerList.size();
		boolean flag = true;
		// 如A23456等，若为A 2 3 5 6 7则不为顺子
		if (pokerList.get(0).getNum() == PokerConstatns.POKER_NUM_THREE
				&& pokerList.get(pokerListLen - 2).getNum() == PokerConstatns.POKER_NUM_ONE
				&& pokerList.get(pokerListLen - 1).getNum() == PokerConstatns.POKER_NUM_TWO) {
			int lastNum = pokerList.get(0).getNum();
			for (int i = 1; i < pokerListLen - 2; i++) {
				int temps = pokerList.get(i).getNum();
				if (getIndexFromPOKER_POWER_ARRAY(temps) != getIndexFromPOKER_POWER_ARRAY(lastNum) - 1) {
					return false;
				}
				lastNum = temps;
			}
			return true;
		} else {
			// 如8 9 10 J Q K A 2，不是顺子
			if (pokerList.get(0).getNum() != PokerConstatns.POKER_NUM_THREE
					&& pokerList.get(pokerListLen - 1).getNum() == PokerConstatns.POKER_NUM_TWO) {
				return false;
			}
			int lastNum = pokerList.get(0).getNum();
			for (int i = 1; i < pokerListLen; i++) {
				int num = pokerList.get(i).getNum();
				if (getIndexFromPOKER_POWER_ARRAY(num) != getIndexFromPOKER_POWER_ARRAY(lastNum) - 1) {
					flag = false;
					break;
				}
				lastNum = num;
			}
		}
		return flag;
	}

	/**
	 * 判断是否是连对(22 33 44)
	 * 
	 * @param pokerList
	 * @return
	 */
	public static boolean isLiandui(List<Poker> pokerList) {
		boolean flag = true;
		int size = pokerList.size();
		if (size >= 6 && size % 2 == 0) {// 三对以上算连对，且必须是双数
			pokerList = sortPokerList(pokerList);
			int lastPokerNum = 0;
			List<Poker> tempList = new ArrayList<Poker>();
			// 判断每2张牌是否相同
			for (int i = 0; i < size; i += 2) {
				int pokerNum = pokerList.get(i).getNum();
				int pokerNum2 = pokerList.get(i + 1).getNum();
				tempList.add(pokerList.get(i));
				if (pokerNum != pokerNum2) {
					flag = false;
					break;
				}
				if (lastPokerNum == 0) {
					lastPokerNum = pokerNum;
					continue;
				}
			}
			// TODO 最终的判断，目前判断有问题
			if (!isShun(tempList)) {
				return false;
			}
		} else {
			flag = false;
		}
		return flag;
	}

	/**
	 * 判断是否是三带一(888 5)
	 * 
	 * @param pokerList
	 * @return
	 */
	public static boolean isThreeWithOne(List<Poker> pokerList) {
		boolean flag = false;
		if (pokerList.size() == 4) {
			pokerList = sortPokerList(pokerList);
			if (pokerList.get(0).getNum() != pokerList.get(3).getNum()
					&& pokerList.get(1).getNum() == pokerList.get(2).getNum()) {
				flag = true;
			}
		}
		return flag;
	}

	/**
	 * 判断是否是三带一对(888 AA)
	 * 
	 * @param pokerList
	 * @return
	 */
	public static boolean isThreeWithPair(List<Poker> pokerList) {
		boolean flag = false;
		if (pokerList.size() == 5) {
			pokerList = sortPokerList(pokerList);
			if (pokerList.get(0).getNum() == pokerList.get(1).getNum()
					&& pokerList.get(3).getNum() == pokerList.get(4).getNum()
					&& (pokerList.get(2).getNum() == pokerList.get(3).getNum() || pokerList
							.get(2).getNum() == pokerList.get(0).getNum())) {
				flag = true;
			}
		}
		return flag;
	}

	/**
	 * 判断是否是飞机(888 999)
	 * 
	 * @param pokerList
	 * @return
	 */
	public static boolean isPlane(List<Poker> pokerList) {
		boolean flag = false;
		int size = pokerList.size();
		if (size >= 6 && size % 3 == 0) {
			pokerList = sortPokerList(pokerList);
			for (int i = 0; i < size; i += 3) {
				int temp1 = pokerList.get(i).getNum();
				int temp2 = pokerList.get(i + 1).getNum();
				int temp3 = pokerList.get(i + 2).getNum();
				if (temp1 != temp2 || temp1 != temp3) {
					return false;
				}
			}
			flag = true;
		}
		return flag;
	}

	/**
	 * 判断是否是飞机带翅膀(6 333444 8)
	 * 
	 * @param pokerList
	 * @return
	 */
	public static boolean isPlaneWithWings(List<Poker> pokerList) {
		boolean flag = false;
		if (pokerList.size() == 8) {
			pokerList = sortPokerList(pokerList);
			List<Poker> tempList = new ArrayList<Poker>();
			for (int i = 0; i < pokerList.size(); i++) {
				tempList.add(pokerList.get(i));
			}
			int poker1 = tempList.get(0).getNum();
			int poker2 = tempList.get(1).getNum();
			int poker3 = tempList.get(2).getNum();
			int poker6 = tempList.get(5).getNum();
			int poker7 = tempList.get(6).getNum();
			int poker8 = tempList.get(7).getNum();
			// 33344468
			if (poker6 != poker7 && poker7 != 8) {
				return checkContainsPlane(tempList, new Integer[] { 7, 6 });
			}
			// 35777888
			if (poker1 != poker2 && poker2 != poker3) {
				return checkContainsPlane(tempList, new Integer[] { 1, 0 });
			}
			// 34445559
			if (poker1 != poker2 && poker7 != poker8) {
				return checkContainsPlane(tempList, new Integer[] { 7, 0 });
			}
		}
		return flag;
	}

	private static boolean checkContainsPlane(List<Poker> tempList,
			Integer[] integers) {
		for (int i = 0; i < integers.length; i++) {
			tempList.remove(integers[i].intValue());
		}
		return isPlane(tempList);
	}

	/**
	 * 判断是否是四带二(7 8888 9)
	 * 
	 * @param pokerList
	 * @return
	 */
	public static boolean isFourWithTwo(List<Poker> pokerList) {
		boolean flag = false;
		if (pokerList.size() == 6) {
			pokerList = sortPokerList(pokerList);
			List<Poker> tempList = new ArrayList<Poker>();
			for (int i = 0; i < pokerList.size(); i++) {
				tempList.add(pokerList.get(i));
			}
			int poker1 = pokerList.get(0).getNum();
			int poker2 = pokerList.get(1).getNum();
			int poker3 = pokerList.get(2).getNum();
			int poker4 = pokerList.get(3).getNum();
			int poker5 = pokerList.get(4).getNum();
			int poker6 = pokerList.get(5).getNum();
			// 333368
			if (poker4 != poker5 && poker5 != poker6) {
				return checkContainsBomb(tempList, new Integer[] { 5, 4 });
			}
			// 377778
			if (poker1 != poker2 && poker5 != poker6) {
				return checkContainsBomb(tempList, new Integer[] { 5, 0 });
			}
			// 349999
			if (poker1 != poker2 && poker2 != poker3) {
				return checkContainsBomb(tempList, new Integer[] { 1, 0 });
			}
			// 334444
			if (poker1 == poker2 && poker2 != poker3) {
				return checkContainsBomb(tempList, new Integer[] { 1, 0 });
			}
			// 444499
			if (poker5 == poker6 && poker5 != poker4) {
				return checkContainsBomb(tempList, new Integer[] { 5, 4 });
			}
		}
		return flag;
	}

	private static boolean checkContainsBomb(List<Poker> tempList,
			Integer[] integers) {
		for (int i = 0; i < integers.length; i++) {
			tempList.remove(integers[i].intValue());
		}
		return isBomb(tempList);
	}

	/**
	 * 判断后一个对子是否比前一个对子大
	 * 
	 * @param pokerList1
	 * @param pokerList2
	 * @return true为大，false为小
	 */
	public static boolean isBiggerPair(List<Poker> pokerList1,
			List<Poker> pokerList2) {
		return isBigger(pokerList1.get(0).getNum(), pokerList2.get(0).getNum());
	}

	/**
	 * 后张牌是否比前张牌大
	 * 
	 * @param poker1
	 * @param poker2
	 * @return
	 */
	private static boolean isBigger(int poker1, int poker2) {
		return getIndexFromPOKER_POWER_ARRAY(poker1) > getIndexFromPOKER_POWER_ARRAY(poker2);
	}

	// 从单张牌大小的数组中获取当前牌的索引
	public static int getIndexFromPOKER_POWER_ARRAY(int num) {
		int len = PokerConstatns.POKER_POWER_ARRAY.length;
		for (int i = 0; i < len; i++) {
			if (PokerConstatns.POKER_POWER_ARRAY[i] == num) {
				return i;
			}
		}
		return len;
	}

	/**
	 * 判断后一个炸弹是否比前一个炸弹大
	 * 
	 * @param pokerList1
	 * @param pokerList2
	 * @return true为大，false为小
	 */
	public static boolean isBiggerBomb(List<Poker> pokerList1,
			List<Poker> pokerList2) {
		return isBigger(pokerList1.get(0).getNum(), pokerList2.get(0).getNum());
	}

	/**
	 * 判断后一个顺子是否比前一个顺子大
	 * 
	 * @param pokerList1
	 * @param pokerList2
	 * @return true为大，false为小
	 */
	public static boolean isBiggerShunzi(List<Poker> pokerList1,
			List<Poker> pokerList2) {
		int len = pokerList1.size() - 1;
		return isBigger(pokerList1.get(len).getNum(), pokerList2.get(len)
				.getNum());
	}

	/**
	 * 判断后一个连对是否比前一个连对大
	 * 
	 * @param pokerList1
	 * @param pokerList2
	 * @return
	 */
	public static boolean isBiggerLiandui(List<Poker> pokerList1,
			List<Poker> pokerList2) {
		int len = pokerList1.size() - 1;
		return isBigger(pokerList1.get(len).getNum(), pokerList2.get(len)
				.getNum());
	}

	/**
	 * 判断后一个三带一是否比前一个三带一大
	 * 
	 * @param pokerList1
	 * @param pokerList2
	 * @return
	 */
	public static boolean isBiggerThreeWithOne(List<Poker> pokerList1,
			List<Poker> pokerList2) {
		// 只能是 4445 或 4555这种情况，第2和3位为三个对应的数字
		return isBigger(pokerList1.get(2).getNum(), pokerList2.get(2).getNum());
	}

	/**
	 * 判断后一个三带一对是否比前一个三带一对大
	 * 
	 * @param pokerList1
	 * @param pokerList2
	 * @return
	 */
	public static boolean isBiggerThreeWithPair(List<Poker> pokerList1,
			List<Poker> pokerList2) {
		// 44455和66677的比较只需要比第3张，44455和55666也是一样
		return isBigger(pokerList1.get(2).getNum(), pokerList2.get(2).getNum());
	}

	/**
	 * 判断后一个飞机是否比前一个飞机大
	 * 
	 * @param pokerList1
	 * @param pokerList2
	 * @return
	 */
	public static boolean isBiggerPlane(List<Poker> pokerList1,
			List<Poker> pokerList2) {
		return isBigger(pokerList1.get(0).getNum(), pokerList2.get(0).getNum());
	}

	/**
	 * 判断后一个飞机带翅膀是否比前一个飞机带翅膀大
	 * 
	 * @param pokerList1
	 * @param pokerList2
	 * @return
	 */
	public static boolean isBiggerPlaneWithWings(List<Poker> pokerList1,
			List<Poker> pokerList2) {
		// 飞机带单牌各1张的如：4445556 33444555 44455566
		// 飞机带单牌各1对的如：3344455566(暂时不支持)
		// 上面4种都只需要比第三张的大小
		return isBigger(pokerList1.get(2).getNum(), pokerList2.get(2).getNum());
	}

	/**
	 * 判断是否是更大的四带二
	 * 
	 * @param pokerList1
	 * @param pokerList2
	 * @return
	 */
	public static boolean isBiggerFourWithTwo(List<Poker> pokerList1,
			List<Poker> pokerList2) {
		// 333368
		// 377778
		// 349999
		// 334444
		// 444499
		// 以上5种都只需要判断第三张的大小
		return isBigger(pokerList1.get(2).getNum(), pokerList2.get(2).getNum());
	}

	/**
	 * 根据扑克获取扑克对应的资源的名称
	 * 
	 * @param poker
	 * @return
	 */
	public static String getPokerName(Poker poker) {
		StringBuffer sb = new StringBuffer();
		int color = poker.getColor();
		int num = poker.getNum();
		if (color != PokerConstatns.POKER_COLOR_KING) {
			String temp = num + "";
			if (temp.equals("1")) {
				temp = "a";
			}
			if (temp.equals("11")) {
				temp = "j";
			}
			if (temp.equals("12")) {
				temp = "q";
			}
			if (temp.equals("13")) {
				temp = "k";
			}
			sb.append(PokerConstatns.POKER_COLOR_MAP.get(color) + "_" + temp);
		} else {
			if (num == PokerConstatns.POKER_NUM_OLD_KING) {
				return "old_king";
			}
			if (num == PokerConstatns.POKER_NUM_YONG_KING) {
				return "young_king";
			}
		}
		return sb.toString();
	}
}
